/*
 * @Author: xiaosihan
 * @Date: 2024-06-20 21:38:49
 * @Last Modified by: xiaosihan
 * @Last Modified time: 2024-10-01 19:24:05
 */

import extractMaterial from "@views/pc/PartCollaborate/Model3d/extractMaterial";
import { get } from "lodash";
import {
  Color,
  DoubleSide,
  Group,
  Mesh,
  MeshStandardMaterial,
  NormalBlending,
  Object3D,
  Vector3,
} from "three";
import threeLoader from "three-base/threeLoader";
import threeUtils from "three-base/threeUtils";

// 爆炸模型
export default class BlastMesh extends Group {
  constructor() {
    super();
  }
  // 这个模型的大小
  size = new Vector3(1, 1, 1);

  // 把需要爆炸的模型放到这个组里面
  blastGroup = (() => {
    const blastGroup = new Group();
    this.add(blastGroup);
    return blastGroup;
  })();

  //保存每个模型对象的爆炸方向
  blastDirection: Map<string, Vector3> = new Map();

  //保存每个模型的原来的位置
  meshOriginPosition: Map<string, Vector3> = new Map();

  //模型的中心点
  meshCenter = new Vector3();

  clear() {
    //清空对象爆炸方向
    this.blastDirection.clear();
    //清空爆炸组
    this.blastGroup.clear();
    return this;
  }

  //加载模型
  async loadModel(url: string = "", filename: string = "") {
    if (!url) {
      return;
    }

    const extension = get((filename || url).match(/\.\w+(?=(\?|$))/), [0]);
    const mesh = await threeLoader.loadModel(url, `.${extension}`);

    //模型数组
    const meshs: Array<Mesh> = [];

    threeUtils.center(mesh);
    threeUtils.applyAllTranstion(mesh);
    this.size = threeUtils.getSize(mesh);

    //把模型都放到爆炸组里
    mesh.traverse((o: any) => {
      const m = o as Mesh;
      if (m.isMesh) {
        //把模型对象加入爆炸组,方便操作
        m.frustumCulled = false;
        meshs.push(m);
      }
    });
    meshs.map((m) => {
      m.children = [];
    });
    this.clear();
    this.blastGroup.add(...meshs);

    threeUtils.getCenter(this.blastGroup);

    this.meshCenter.copy(threeUtils.getCenter(this.blastGroup));

    this.blastGroup.children.map((o, i) => {
      const m = o as Mesh;
      if (m.isMesh) {
        // 记录网格模型的中心点为初始方向向量
        this.blastDirection.set(
          m.uuid,
          threeUtils.getCenter(m).sub(this.meshCenter)
        );
        this.meshOriginPosition.set(m.uuid, m.position.clone());
      }
    });

    //加载完成事件
    this.dispatchEvent({ type: "loaded" } as never);

    //更新爆炸进度
    this.setBlastProgress(this.blastProgress);
  }

  // 爆炸进度
  blastProgress = 0;

  // 设置爆炸进度
  setBlastProgress(blastProgress: number) {
    this.blastProgress = blastProgress;
    this.blastGroup.traverse((o) => {
      //根据爆炸进度和爆炸方向计算模型的位置
      const blastNormal = this.blastDirection.get(o.uuid);
      const originPosition = this.meshOriginPosition.get(o.uuid);
      if (blastNormal && originPosition) {
        o.position
          .copy(blastNormal)
          .multiplyScalar(this.blastProgress)
          .add(originPosition);
      }
    });
  }

  //遍历模型
  async traverseMesh(callback: (mesh: Mesh) => void) {
    this.traverse((obj) => {
      const mesh = obj as Mesh;
      if (mesh.isMesh) {
        callback(mesh);
      }
    });
  }
}
